﻿#region

using System;
using DomainModel.Domain.Model;
using DomainModel.Domain.Model.MessageTypeModel;
using DomainModel.Domain.Model.ServiceModel;
using EsbMonitor.Ninject;
using EsbMonitorMessages.Events;
using NServiceBus;

#endregion

namespace EsbMonitor.Handlers
{
    public class HandlerStartedEventHandler : IHandleMessages<IHandlerStarted>
    {
        private const int NoServiceFailMax = 5;
        private const int NoMessageTypeFailMax = 5;

        public IBus Bus { get; set; }

        public void Handle(IHandlerStarted message)
        {
            var servicesRepository = KernelContainer.Get<IServicesRepository>();

            QueueInfo queueInfo = new QueueInfo(message.ServiceInfo.InputQueue.QueueName);

            Service service = servicesRepository.Get(queueInfo);

            if (service == null)
            {
                HandleNoServiceSituation();
                return;
            }

            MessageType messageType = service.FindMessageType(message.HandledType.MessageAssemblyInfo.MessageAssemblyName, message.HandledType.TypeName);

            if (messageType == null)
            {
                HandleNoMessageTypeSituation();
                return;
            }

            HandlerRole handlerRole = new HandlerRole(servicesRepository.NextServiceRoleId());
            handlerRole.CreateModifyInfo = new CreateModifyInfo
                                               {
                                                   Created = DateTime.Now,
                                                   LastModified = DateTime.Now
                                               };
            handlerRole.HandledType = messageType;

            service.AddServiceRole(handlerRole);

            servicesRepository.Store(service);
        }

        private void HandleNoMessageTypeSituation()
        {
            HandleLaterUnlessMaxFailTimesHasBeenReached("failed_no_message_type", NoMessageTypeFailMax);
        }

        private void HandleNoServiceSituation()
        {
            HandleLaterUnlessMaxFailTimesHasBeenReached("failed_no_service", NoServiceFailMax);
        }

        private void HandleLaterUnlessMaxFailTimesHasBeenReached(string key, int max)
        {
            if (!Bus.CurrentMessageContext.Headers.ContainsKey(key))
            {
                Bus.CurrentMessageContext.Headers.Add(key, "1");
                Bus.HandleCurrentMessageLater();
                return;
            }

            int count = int.Parse(Bus.CurrentMessageContext.Headers[key]);

            if (count != max)
            {
                Bus.CurrentMessageContext.Headers[key] = (count+1).ToString();
                Bus.HandleCurrentMessageLater();
            }
        }
    }
}